#ifndef MATH_TUPLE_HPP
#define MATH_TUPLE_HPP

/**
 * @mainpage Tuple
 * @author Alberto De Pena
 *
 *This is a class that emulates a vector. Several operators are overloaded in order
 *to facilitate the users with the common functionlaity of common operators.
 */
/**
 * @file Tuple.hpp
 * 
 * This header file contains the prototypes of the functions needed to manipulate a Tuple 
 * object.
 */
#include <iostream>
#include <string>

/**
 * The namespace math encapsulates the prototype (declarations) of the functions that will be
 * available for the user to incorporate in his/her program.
 */

namespace math
{
/**
 * This class specifies the manner in which the Tuple object can be implemented.
 */
	class Tuple
	{
	public:
		Tuple();
		Tuple( const Tuple& tuple );
		Tuple( unsigned int size, const double tuple[] );
		explicit Tuple( unsigned int size );
		~Tuple();

		unsigned int getSize() const;

		double dot( const Tuple& tuple ) const;
		double length() const;

		void print( std::ostream& out ) const;

		double& operator[]( unsigned int t );
		const double& operator[]( unsigned int t ) const;

		Tuple& operator=( const Tuple& tuple );

		bool operator==( const Tuple& tuple ) const;
        bool operator!=( const Tuple& tuple ) const;

		Tuple operator*=( const double& t ) const;
        Tuple operator/=( const double& t ) const;

		Tuple& operator+=( const Tuple& tuple );
		Tuple& operator-=( const Tuple& tuple );

		Tuple operator+( const Tuple& tuple ) const;
        Tuple operator-( const Tuple& tuple ) const;
        Tuple operator*( const double& t ) const;
        Tuple operator/( const double& t ) const;

		Tuple operator-() const;

		friend Tuple operator*( const double t, const Tuple& tuple );

	/**
	 * This class throws an exception every time the user sets the index to an invalid value.
	 */
		class OutOfBounds
		{
		public:
			OutOfBounds( std:: string message );

			const char * what() const;
		private:
			//Variable that contains a specific message to throw an exception when invalid index has been entered.
			std::string error_message;
		};

	/**
	 * This class throws an exception if two Tuples are of different size.
	 */
		class SizeMismatch
		{
		public:
			SizeMismatch( std::string message );

			const char * what() const;
		private:
			//Variable that contains a specific message to throw an exception when two Tuples are not the
			//same size.
			std::string error_message;
		};

	private:
		//elementTuple is a pointer to an array of doubles ( Tuple ).
		double* elementTuple;
		//sizeTuple is a variable that contains the size of the Tuple.
		unsigned int sizeTuple;
	};
	
	inline std::ostream& operator<<( std::ostream& out, const Tuple& t )
    {
        t.print( out );
        return out;
    }
}
#endif